/** \file chatgpt.c 
 *  \brief chatgpt
 */
#include <assert.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <string>

#include "rk_mpi_amix.h"
//#include "speechnls.h" 

#include "het_ringbuf.h" 
#include "het_ringbuf.h" 
#include "het_chatgpt.h"  // <-- 唯一必须包含的头文件

#define SPEAKE_MIN_VALUE 10000

#define WAIT_THRESHOLD 10
#define SEND_THRESHOLD 5
#define SPEAK_THRESHOLD 1000

static RK_S32 loopCount = 0;
static RK_BOOL isNeedApply = RK_TRUE;
/**
 * @brief 获取音频数据
 * @param ctx 音频参数
 * @param pdata 音频数据返回地址
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_GetFrame(HET_AI_CTX_S *ctx, void **pdata) {
	RK_S32 s32Ret = RK_FAILURE;
	RK_S32 s32MilliSec = -1;
	// HET_LOGD("read data s32DevId %d,s32ChnId %d,s32MilliSec %d !\r\n", ctx->s32DevId, ctx->s32ChnId,s32MilliSec);
	s32Ret = RK_MPI_AI_GetFrame(ctx->s32DevId, ctx->s32ChnId, &ctx->stFrame, RK_NULL,
	                            s32MilliSec);
	if (s32Ret == RK_SUCCESS) {
		*pdata = RK_MPI_MB_Handle2VirAddr(ctx->stFrame.pMbBlk);
	} else {
		HET_LOGE("RK_MPI_AI_GetFrame failed with %#x!\r\n", s32Ret);
	}

	return 0;
}
/**
 * @brief 释放音频数据
 * @param ctx 音频参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_ReleaseFrame(HET_AI_CTX_S *ctx) {
	RK_S32 s32Ret = RK_FAILURE;

	s32Ret = RK_MPI_AI_ReleaseFrame(ctx->s32DevId, ctx->s32ChnId, &ctx->stFrame, RK_NULL);
	if (s32Ret != RK_SUCCESS) {
		HET_LOGE("RK_MPI_AI_ReleaseFrame failed with %#x!\r\n", s32Ret);
		return RK_FAILURE;
	}

	return RK_SUCCESS;
}

/**
 * 应用增强效果
 */
RK_S32 apply_ai_aed(HET_AI_CTX_S *params) {//1
    RK_S32 result;
	AI_AED_CONFIG_S stAiAedConfig, stAiAedConfig2;

    if (params->s32AedEnable == 0){
		HET_LOGE("dev %d chn %d not enable aed\r\n",
			 params->s32DevId, params->s32ChnId);
             
		RK_MPI_AI_DisableAed(g_ctx.ai.s32DevId, g_ctx.ai.s32ChnId);
		return 0;
	}
	stAiAedConfig.fSnrDB = params->fSnrDB;
	stAiAedConfig.fLsdDB = params->fLsdDB;
	stAiAedConfig.s32Policy = params->s32AedPolicy;

	result = RK_MPI_AI_SetAedAttr(params->s32DevId, params->s32ChnId, &stAiAedConfig);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetAedAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = RK_MPI_AI_GetAedAttr(params->s32DevId, params->s32ChnId, &stAiAedConfig2);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetAedAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = memcmp(&stAiAedConfig, &stAiAedConfig2, sizeof(AI_AED_CONFIG_S));
	if (result != RK_SUCCESS) {
		HET_LOGE("set/get aed config is different: %d\r\n",  result);
		return result;
	}

	result = RK_MPI_AI_EnableAed(params->s32DevId, params->s32ChnId);
	if (result != RK_SUCCESS) {
		HET_LOGE("EnableAed(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	HET_LOGI("apply_ai_aed RK_SUCCESS!!!\r\n");
    return RK_SUCCESS;
}
/**
 * 
 */
RK_S32 apply_ai_bcd(HET_AI_CTX_S *params) {
	RK_S32 result;
	AI_BCD_CONFIG_S stAiBcdConfig, stAiBcdConfig2;
	
    if (params->s32BcdEnable == 0){
		HET_LOGE("dev %d chn %d not enable bcd\r\n",
			 params->s32DevId, params->s32ChnId);
		return 0;
	}

	stAiBcdConfig.mFrameLen = 100;

	result = RK_MPI_AI_SetBcdAttr(params->s32DevId, params->s32ChnId, &stAiBcdConfig);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetBcdAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = RK_MPI_AI_GetBcdAttr(params->s32DevId, params->s32ChnId, &stAiBcdConfig2);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetBcdAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = memcmp(&stAiBcdConfig, &stAiBcdConfig2, sizeof(AI_BCD_CONFIG_S));
	if (result != RK_SUCCESS) {
		HET_LOGE("set/get aed config is different: %d\r\n",  result);
		return result;
	}

	result = RK_MPI_AI_EnableBcd(params->s32DevId, params->s32ChnId);
	if (result != RK_SUCCESS) {
		HET_LOGE("EnableBcd(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

    return RK_SUCCESS;
}

/**
 * 
 */

RK_S32 apply_ai_buz(HET_AI_CTX_S *params) {
    RK_S32 result;

	AI_BUZ_CONFIG_S stAiBuzConfig, stAiBuzConfig2;
	
    if (params->s32BuzEnable == 0){
		HET_LOGE("dev %d chn %d not enable buz\r\n",
			 params->s32DevId, params->s32ChnId);
		return 0;
	}

	stAiBuzConfig.mFrameLen = 100;

	result = RK_MPI_AI_SetBuzAttr(params->s32DevId, params->s32ChnId, &stAiBuzConfig);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetBuzAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = RK_MPI_AI_GetBuzAttr(params->s32DevId, params->s32ChnId, &stAiBuzConfig2);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetBuzAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = memcmp(&stAiBuzConfig, &stAiBuzConfig2, sizeof(AI_BUZ_CONFIG_S));
	if (result != RK_SUCCESS) {
		HET_LOGE("set/get aed config is different: %d\r\n",  result);
		return result;
	}

	result = RK_MPI_AI_EnableBuz(params->s32DevId, params->s32ChnId);
	if (result != RK_SUCCESS) {
		HET_LOGE("EnableBuz(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

    return RK_SUCCESS;
}

/**
 * @brief 创建音频通道 
 * @param ctx 音频通道参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 apply_ai_gbs(HET_AI_CTX_S *params) {//30
    RK_S32 result;

	AI_GBS_CONFIG_S stAiGbsConfig, stAiGbsConfig2;
	
    if (params->s32GbsEnable == 0){
		HET_LOGE("dev %d chn %d not enable gbs\r\n",
			 params->s32DevId, params->s32ChnId);
		return 0;
	}

	stAiGbsConfig.mFrameLen = params->s32GbsFrameLen;

	result = RK_MPI_AI_SetGbsAttr(params->s32DevId, params->s32ChnId, &stAiGbsConfig);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetGbsAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = RK_MPI_AI_GetGbsAttr(params->s32DevId, params->s32ChnId, &stAiGbsConfig2);
	if (result != RK_SUCCESS) {
		HET_LOGE("SetGbsAttr(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}

	result = memcmp(&stAiGbsConfig, &stAiGbsConfig2, sizeof(AI_GBS_CONFIG_S));
	if (result != RK_SUCCESS) {
		HET_LOGE("set/get aed config is different: %d\r\n",  result);
		return result;
	}

	result = RK_MPI_AI_EnableGbs(params->s32DevId, params->s32ChnId);
	if (result != RK_SUCCESS) {
		HET_LOGE("EnableGbs(%d,%d) failed with %#x\r\n",
			 params->s32DevId, params->s32ChnId, result);
		return result;
	}
    return RK_SUCCESS;
}

/**
 * @brief 创建音频通道 
 * @param ctx 音频通道参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 apply_ai_vqe(HET_AI_CTX_S *params) {
    AI_VQE_CONFIG_S stAiVqeConfig, stAiVqeConfig2;
    AI_VQE_MOD_ENABLE_S stAiVqeModEnable;
    RK_S32 result;

    if (params->s32VqeEnable == 0){
		HET_LOGE("dev %d chn %d not enable Vqe\r\n",
			 params->s32DevId, params->s32ChnId);
        result = RK_MPI_AI_DisableVqe(params->s32DevId, params->s32ChnId);
        if (result != RK_SUCCESS) {
            HET_LOGE("DisableVqe(%d,%d) failed with %#x\r\n",
                params->s32DevId, params->s32ChnId, result);
            return result;
        }
        return RK_SUCCESS;
    }else if (params->s32VqeEnable == 2) {
        //When it is necessary to configure module switches separately, this interface needs to be called.
        //By default, it can be ignored.
        #if 1
        //By default, it can be ignored.
        stAiVqeModEnable.bAec = RK_TRUE;
        stAiVqeModEnable.bBf = RK_TRUE;
        stAiVqeModEnable.bFastAec = RK_TRUE;
        stAiVqeModEnable.bAes = RK_TRUE;
        stAiVqeModEnable.bGsc = RK_TRUE;
        stAiVqeModEnable.bAgc = RK_TRUE;
        stAiVqeModEnable.bAnr = RK_TRUE;
        stAiVqeModEnable.bNlp = RK_FALSE; //not support
        stAiVqeModEnable.bDereverb = RK_TRUE;
        stAiVqeModEnable.bCng = RK_TRUE;
        stAiVqeModEnable.bDtd = RK_TRUE;
        stAiVqeModEnable.bHowling = RK_TRUE;
        stAiVqeModEnable.bDoa = RK_TRUE;
        #else
        /*
        stAiVqeModEnable.bAec = RK_TRUE;
        stAiVqeModEnable.bBf = RK_TRUE;
        stAiVqeModEnable.bFastAec = RK_TRUE;
        stAiVqeModEnable.bAes = RK_TRUE;
        stAiVqeModEnable.bGsc = RK_TRUE;
        stAiVqeModEnable.bAgc = RK_TRUE;
        stAiVqeModEnable.bAnr = RK_TRUE;
        stAiVqeModEnable.bNlp = RK_FALSE; //not support
        stAiVqeModEnable.bDereverb = RK_TRUE;
        stAiVqeModEnable.bCng = RK_TRUE;
        stAiVqeModEnable.bDtd = RK_TRUE;
        stAiVqeModEnable.bHowling = RK_TRUE;
        stAiVqeModEnable.bDoa = RK_TRUE;
        RK_BOOL bAec;//回声消除模块使能
        RK_BOOL bBf;//波束形成模块使能
        RK_BOOL bFastAec;//线性残留回声消除模块使能
        RK_BOOL bAes;//⾮线性残留回声消除模块使能
        RK_BOOL bWakeup;// 唤醒模块使能
        RK_BOOL bGsc;//开波束后滤波模块使能
        RK_BOOL bAgc;//⾃动增益控制模块使能
        RK_BOOL bAnr; //⾃动降噪模块使能
        RK_BOOL bNlp;//⾮线性残留回声消除模块使能
        RK_BOOL bDereverb;//去混响模块使能
        RK_BOOL bCng;//舒适度噪声模块使能
        RK_BOOL bDtd;//双讲检测模块使能
         */

        stAiVqeModEnable.bAec = RK_TRUE;//回声消除模块使能
        stAiVqeModEnable.bBf = RK_FALSE;
        stAiVqeModEnable.bFastAec = RK_FALSE;//线性残留回声消除模块使能
        stAiVqeModEnable.bAes = RK_FALSE;//⾮线性残留回声消除模块使能
        stAiVqeModEnable.bGsc = RK_FALSE;
        stAiVqeModEnable.bAgc = RK_FALSE;//⾃动增益控制模块使能
        stAiVqeModEnable.bAnr = RK_FALSE;//⾃动降噪模块使能
        stAiVqeModEnable.bNlp = RK_FALSE; //not support
        stAiVqeModEnable.bDereverb = RK_FALSE;
        stAiVqeModEnable.bCng = RK_FALSE;
        stAiVqeModEnable.bDtd = RK_FALSE;
        stAiVqeModEnable.bHowling = RK_FALSE;
        stAiVqeModEnable.bDoa = RK_FALSE;
        #endif
        //When it is necessary to configure module switches separately, this interface needs to be called.
        //By default, it can be ignored.
        result = RK_MPI_AI_SetVqeModuleEnable(params->s32DevId, params->s32ChnId, &stAiVqeModEnable);
        if (result != RK_SUCCESS) {
            HET_LOGE("RK_MPI_AI_SetVqeModuleEnable(%d,%d) failed with %#x\r\n",
                 params->s32DevId, params->s32ChnId, result);
            return result;
        }
    }

    // Need to config enCfgMode to VQE attr even the VQE is not enabled
    memset(&stAiVqeConfig, 0, sizeof(AI_VQE_CONFIG_S));
    if (params->pVqeCfgPath != RK_NULL) {
        stAiVqeConfig.enCfgMode = AIO_VQE_CONFIG_LOAD_FILE;
        memcpy(stAiVqeConfig.aCfgFile, params->pVqeCfgPath, strlen(params->pVqeCfgPath));
    }

    if (params->s32VqeGapMs != 16 && params->s32VqeGapMs != 10) {
        HET_LOGE("Invalid gap: %d, just supports 16ms or 10ms for AI VQE\r\n", params->s32VqeGapMs);
        return RK_FAILURE;
    }

    stAiVqeConfig.s32WorkSampleRate = params->s32ChnSampleRate;
    stAiVqeConfig.s32FrameSample = params->s32ChnSampleRate * params->s32VqeGapMs / 1000;
    stAiVqeConfig.s64RefChannelType = 2;// 0x10 表示第二个通道为回采数据
    stAiVqeConfig.s64RecChannelType = 1;// 0x01 表示第一个通道为录音数据
    for (int i = 0; i < params->s32DeviceChannel; i++)
        stAiVqeConfig.s64ChannelLayoutType |= (1 << i);

    result = RK_MPI_AI_SetVqeAttr(params->s32DevId, params->s32ChnId, 0, 0, &stAiVqeConfig);
    if (result != RK_SUCCESS) {
        HET_LOGE("SetVqeAttr(%d,%d) failed with %#x\r\n",
             params->s32DevId, params->s32ChnId, result);
        return result;
    }

    result = RK_MPI_AI_GetVqeAttr(params->s32DevId, params->s32ChnId, &stAiVqeConfig2);
    if (result != RK_SUCCESS) {
        HET_LOGE("SetVqeAttr(%d,%d) failed with %#x\r\n",
             params->s32DevId, params->s32ChnId, result);
        return result;
    }

    result = memcmp(&stAiVqeConfig, &stAiVqeConfig2, sizeof(AI_VQE_CONFIG_S));
    if (result != RK_SUCCESS) {
        HET_LOGE("set/get vqe config is different: %d\r\n", result);
        return result;
    }

    result = RK_MPI_AI_EnableVqe(params->s32DevId, params->s32ChnId);
    if (result != RK_SUCCESS) {
        HET_LOGE("EnableVqe(%d,%d) failed with %#x\r\n",
             params->s32DevId, params->s32ChnId, result);
        return result;
    }

    return RK_SUCCESS;
}
/**
 * @brief 查找音频输出模式
 * @param ch 通道数
 * @return 音频输出模式
 */
static AUDIO_SOUND_MODE_E HET_AI_Find_Sound_Mode(RK_S32 ch) {
    AUDIO_SOUND_MODE_E channel = AUDIO_SOUND_MODE_BUTT;
    switch (ch) {
      case 1:
        channel = AUDIO_SOUND_MODE_MONO;
        break;
      case 2:
        channel = AUDIO_SOUND_MODE_STEREO;
        break;
      default:
        HET_LOGE("channel = %d not support\r\n", ch);
        return AUDIO_SOUND_MODE_BUTT;
    }

    return channel;
}
/**
 * @brief 应用音频参数
 * @param params 音频通道参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_ApplyChn(HET_AI_CTX_S *params) {

    AUDIO_FADE_S aFade;
    aFade.bFade = RK_FALSE;
    aFade.enFadeOutRate = (AUDIO_FADE_RATE_E)params->s32SetFadeRate;
    aFade.enFadeInRate = (AUDIO_FADE_RATE_E)params->s32SetFadeRate;
    RK_BOOL mute = (params->s32SetMute == 0) ? RK_FALSE : RK_TRUE;
    HET_LOGD("ai info : mute = %d, volume = %d\r\n", mute, params->s32SetVolume);
    RK_MPI_AI_SetMute(params->s32DevId, mute, &aFade);
    if(params->s32SetVolume != -1)
        RK_MPI_AI_SetVolume(params->s32DevId, params->s32SetVolume);

    RK_LOGI("Set volume curve type: %d", params->s32SetVolumeCurve);

    if ((params->s32SetVolumeCurve == AUDIO_CURVE_LOGARITHM) ||
        (params->s32SetVolumeCurve == AUDIO_CURVE_CUSTOMIZE)) {
        AUDIO_VOLUME_CURVE_S volumeCurve;

        volumeCurve.enCurveType = (AUDIO_VOLUME_CURVE_E)params->s32SetVolumeCurve;
        volumeCurve.s32Resolution = 101;
        volumeCurve.fMinDB = -51.0f;
        volumeCurve.fMaxDB = 0.0f;
        volumeCurve.pCurveTable = RK_NULL; // here none means using default logarithm curve by default.
        if (volumeCurve.enCurveType == AUDIO_CURVE_CUSTOMIZE) {
            volumeCurve.pCurveTable = (RK_U32 *)calloc(volumeCurve.s32Resolution, sizeof(RK_U32));
            RK_ASSERT(volumeCurve.pCurveTable != RK_NULL);
            // TODO: fill your customize table of volume curve folllowing to:
            // volumeCurve.pCurveTable[0, resolution-1]
        }
        RK_MPI_AI_SetVolumeCurve(params->s32DevId, &volumeCurve);
    }

    if (params->s32SetTrackMode) {
        HET_LOGD("ai info : set track mode = %d\r\n", params->s32SetTrackMode);
        RK_MPI_AI_SetTrackMode(params->s32DevId, (AUDIO_TRACK_MODE_E)params->s32SetTrackMode);
        params->s32SetTrackMode = 0;
    }

    if (params->s32GetVolume) {
        RK_S32 volume = 0;
        RK_MPI_AI_GetVolume(params->s32DevId, &volume);
        HET_LOGD("ai info : get volume = %d\r\n", volume);
        params->s32GetVolume = 0;
    }

    if (params->s32GetMute) {
        RK_BOOL mute = RK_FALSE;
        AUDIO_FADE_S fade;
        RK_MPI_AI_GetMute(params->s32DevId, &mute, &fade);
        HET_LOGD("ai info : is mute = %d\r\n", mute);
        params->s32GetMute = 0;
    }

    if (params->s32GetTrackMode) {
        AUDIO_TRACK_MODE_E trackMode;
        RK_MPI_AI_GetTrackMode(params->s32DevId, &trackMode);
        HET_LOGD("ai info : get track mode = %d\r\n", trackMode);
        params->s32GetTrackMode = 0;
    }
    return 0;
}

/**
 * @brief 销毁音频通道 
 * @param ctx 音频通道参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_DestroyChn(HET_AI_CTX_S *ctx) {
	RK_S32 s32Ret = RK_FAILURE;
    if (ctx->s32BuzEnable != 0){
        RK_MPI_AI_DisableBuz(ctx->s32DevId, ctx->s32ChnId);
    }
    if (ctx->s32BcdEnable != 0){
        RK_MPI_AI_DisableBcd(ctx->s32DevId, ctx->s32ChnId);
    }
    if (ctx->s32GbsEnable != 0){
        RK_MPI_AI_DisableGbs(ctx->s32DevId, ctx->s32ChnId);
    }
    if (ctx->s32AedEnable != 0){
        RK_MPI_AI_DisableAed(ctx->s32DevId, ctx->s32ChnId);
    }
    if (ctx->s32VqeEnable != 0){
        RK_MPI_AI_DisableVqe(ctx->s32DevId, ctx->s32ChnId);
    }
    // set sample rate of input data
	RK_BOOL needResample = (ctx->stAiAttr.enSamplerate != ctx->stAiAttr.soundCard.sampleRate) ? RK_TRUE : RK_FALSE;
    if (needResample == RK_TRUE) 
    {
	    s32Ret = RK_MPI_AI_DisableReSmp(ctx->s32DevId, ctx->s32ChnId);
        if (s32Ret != RK_SUCCESS) {
            HET_LOGE("AI_DisableReSmp failed with %#x!\r\n", s32Ret);
            return RK_FAILURE;
        }
	}

	s32Ret |= RK_MPI_AI_DisableChn(ctx->s32DevId, ctx->s32ChnId);
	if (s32Ret != RK_SUCCESS) {
		HET_LOGE("AI_DisableChn failed with %#x!\r\n", s32Ret);
		//return RK_FAILURE;
	}

	s32Ret = RK_MPI_AI_Disable(ctx->s32DevId);
	if (s32Ret != RK_SUCCESS) {
		HET_LOGE("AI_Disable failed with %#x!\r\n", s32Ret);
		return RK_FAILURE;
	}
	if(ctx->AudioData){
		free(ctx->AudioData);
        ctx->AudioData = NULL;
	}
	return RK_SUCCESS;
}


/**
 * @brief 创建音频通道 
 * @param ctx 音频通道参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_CreateChn(HET_AI_CTX_S *params) {
	RK_S32 result = RK_FAILURE;

	result = RK_MPI_AI_SetPubAttr(params->s32DevId, &params->stAiAttr);
	if (result != RK_SUCCESS) {
		HET_LOGE("AI_SetPubAttr failed with %#x!\r\n", result);
        return result;
    }

    // 先不考虑多通道
	result = RK_MPI_AI_Enable(params->s32DevId);
	if (result != 0) {
		HET_LOGE("AI_Enable failed with %#x!\r\n", result);
        return result;
    }
	AI_CHN_PARAM_S pstParams;

    memset(&pstParams, 0, sizeof(AI_CHN_PARAM_S));
    pstParams.s32UsrFrmDepth = 2;
    result = RK_MPI_AI_SetChnParam(params->s32DevId, params->s32ChnId, &pstParams);
    if (result != RK_SUCCESS) {
        HET_LOGE("set channel params fail, aiChn = %d\r\n", params->s32ChnId);
        return RK_FAILURE;
    }

    result = apply_ai_aed(params);
    if (result != 0) {
        HET_LOGE("ai aed init fail, reason = %x, aiChn = %d\r\n", result, params->s32ChnId);
        return RK_FAILURE;
    }

    result = apply_ai_bcd(params);
    if (result != 0) {
        HET_LOGE("ai bcd init fail, reason = %x, aiChn = %d\r\n", result, params->s32ChnId);
        return RK_FAILURE;
    }

    result = apply_ai_buz(params);
    if (result != 0) {
        HET_LOGE("ai buz init fail, reason = %x, aiChn = %d\r\n", result, params->s32ChnId);
        return RK_FAILURE;
    }

    result = apply_ai_gbs(params);
    if (result != 0) {
        HET_LOGE("ai gbs init fail, reason = %x, aiChn = %d\r\n", result, params->s32ChnId);
        return RK_FAILURE;
    }

    result = apply_ai_vqe(params);
    if (result != 0) {
        HET_LOGE("ai vqe init fail, reason = %x, aiChn = %d\r\n", result, params->s32ChnId);
        return RK_FAILURE;
    }

	result = RK_MPI_AI_EnableChn(params->s32DevId, params->s32ChnId);
    if (result != RK_SUCCESS) {
		HET_LOGE("AI_EnableChn failed with %#x!\r\n", result);
        return result;
    }

    // set sample rate of input data
	RK_BOOL needResample = (params->stAiAttr.enSamplerate != params->stAiAttr.soundCard.sampleRate) ? RK_TRUE : RK_FALSE;

	if (needResample == RK_TRUE) {
		result = RK_MPI_AI_EnableReSmp(params->s32DevId, params->s32ChnId,
									(AUDIO_SAMPLE_RATE_E)params->s32ChnSampleRate);
	    if (result != RK_SUCCESS) {
				HET_LOGE("AI_EnableReSmp failed with %#x!\r\n", result);
	        return result;
	    }
	}

    HET_AI_ApplyChn(params);

	return RK_SUCCESS;
__AICH_EXIT:
    RK_MPI_AI_Disable(params->s32DevId);
    return RK_FAILURE;
}
/**
 * @brief 检测音频数据是否能被读取
 * @param params 音频参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_apply_Data_Read(HET_AI_CTX_S *params) {
    RK_S32 result;

    if (params->s32DataReadEnable) {
        result = RK_MPI_AI_EnableDataRead(params->s32DevId, params->s32ChnId);
        if (result != RK_SUCCESS) {
            HET_LOGE("RK_MPI_AI_EnableDataRead(%d,%d) failed with %#x\r\n",
                 params->s32DevId, params->s32ChnId, result);
            return result;
        }
    }

    return RK_SUCCESS;
}
/**
 * @brief 设置音量
 * @param params 音频参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_apply_Volume(int volume) {
    RK_S32 result;

    g_ctx.ai.s32SetVolume = volume;
    RK_MPI_AI_SetVolume(g_ctx.ai.s32DevId, g_ctx.ai.s32SetVolume);
    return RK_SUCCESS;
}
/**
 * @brief 设置静量
 * @param params 音频参数
 * @return 成功返回0，失败返回-1
 */
RK_S32 HET_AI_apply_Mute(int s32SetMute) {
    RK_S32 result;

    g_ctx.ai.s32SetMute = s32SetMute;
    AUDIO_FADE_S aFade;
    aFade.bFade = RK_FALSE;
    aFade.enFadeOutRate = (AUDIO_FADE_RATE_E)g_ctx.ai.s32SetFadeRate;
    aFade.enFadeInRate = (AUDIO_FADE_RATE_E)g_ctx.ai.s32SetFadeRate;
    RK_BOOL mute = (g_ctx.ai.s32SetMute == 0) ? RK_FALSE : RK_TRUE;
    RK_MPI_AI_SetMute(g_ctx.ai.s32DevId, mute, &aFade);
    return RK_SUCCESS;
}
static void mpi_ai_attr_show_options(const AIO_ATTR_S *ctx,int aiDevId) {
    HET_LOGD("AI_ATTR:%d\r\n", aiDevId);
    HET_LOGD("u8CardName      : %s\r\n", ctx->u8CardName?(char *)ctx->u8CardName:"NULL");
    HET_LOGD("soundCard.channels      : %d\r\n", ctx->soundCard.channels);
    HET_LOGD("soundCard.sampleRate            : %d\r\n", ctx->soundCard.sampleRate);
    HET_LOGD("soundCard.bitWidth        : %d\r\n", ctx->soundCard.bitWidth);
    HET_LOGD("u32ChnCnt          : %d\r\n", ctx->u32ChnCnt);
    HET_LOGD("enBitwidth       : %d\r\n", ctx->enBitwidth);
    HET_LOGD("enSamplerate      : %d\r\n", ctx->enSamplerate);
    HET_LOGD("enSoundmode    : %s\r\n", ctx->enSoundmode==AUDIO_SOUND_MODE_MONO?"AUDIO_SOUND_MODE_MONO":ctx->enSoundmode==AUDIO_SOUND_MODE_STEREO?"AUDIO_SOUND_MODE_STEREO":"OTHER");
    HET_LOGD("u32FrmNum        : %d\r\n", ctx->u32FrmNum);
    HET_LOGD("u32PtNumPerFrm             : %d\r\n", ctx->u32PtNumPerFrm);
    HET_LOGD("u32EXFlag          : %d\r\n", ctx->u32EXFlag);
}

#define SAVE_FILE 0
void het_ai_apply(){
    HET_LOGI("het_ai_apply\r\n");
    isNeedApply =  RK_TRUE;    
}
static char *recFile = NULL;
char* het_ai_has_rec(){
    if(recFile)
        HET_LOGI("het_ai_has_rec\r\n");
    return recFile;    
}
void het_ai_clean_rec_file(char *filename){
    char rmfile[256];
    if(filename && strlen(filename) > 0 && strcmp(filename+strlen(filename)-4,".pcm") == 0){
        memset(rmfile,0,sizeof(rmfile));
        snprintf(rmfile,sizeof(rmfile) - 1,"rm -f %s",filename);
        HET_LOGI("rm cmd:%s\r\n", rmfile);
        system(rmfile);
        rb_reset(&audioRecBuf);
    }
    recFile = NULL;
}
void het_ai_clean_all_rec_file(void){
    char rmfile[256];
    memset(rmfile,0,sizeof(rmfile));
    snprintf(rmfile,sizeof(rmfile) - 1,"rm -f /userdata/cap_out_r*.pcm");
    system(rmfile);
    rb_reset(&audioRecBuf);
}

void het_ai_clean_rec(){
    het_ai_clean_all_rec_file();
    recFile = NULL;
}
#define AI_ALGO_FRAMES 256  // baed on 16kHz, it's  128 during 8kHz
void* getDataThread(HET_AI_CTX_S *params) {

    RK_S32 result = 0;
    char cacheBuf[1024];
    RK_S32 s32MilliSec = 200;
    AUDIO_FRAME_S getFrame;
    char filename[128];
    char rmfile[256];
    RK_S32 fileCount= 0;
    FILE *fp_aed, *fp_bcd, *fp_buz, *fp_gbs,*fp_r=NULL;
    RK_U8  *srcData = RK_NULL;
    RK_S16 *buf_aed, *buf_bcd, *buf_buz, *buf_gbs;
    RK_S32 s32AiAlgoFrames = 0;
    RK_U32 aed_count = 0, aed_flag = 0;
    RK_U32 bcd_count = 0, bcd_flag = 0;
    RK_U32 buz_count = 0, buz_flag = 0;
    RK_U32 gbs_count = 0, gbs_flag = 0;
    // mode1: oneshot words
    const char *mode1_wakeup_words[8] = {
        "No wake\r\n",
        "Wo Yao Pai Zhao\r\n",
        "Guan Bi Re Dian\r\n",
        "Da Kai Re Dian\r\n",
        "Guan Bi Lu Yin\r\n",
        "Da Kai Lu Yin\r\n",
        "Guan Bi Ping Mu\r\n",
        "Da Kai Ping Mu\r\n",
    };
    // mode2: wakeup words
    const char *mode2_wakeup_words[2] = {
        "No wake\r\n",
        "Xiao He Xiao He\r\n",
    };
    // mode2: command words
    const char *mode2_command_words[19] = {
        "No command\r\n",
        "Gei <Ba Ba> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Ba Ba>\r\n",
        "Hu Jiao <Ba Ba>\r\n",
        "Gei <Ma Ma> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Ma Ma>\r\n",
        "Hu Jiao <Ma Ma>\r\n",
        "Gei <Ye Ye> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Ye Ye>\r\n",
        "Hu Jiao <Ye Ye>\r\n",
        "Gei <Nai Nai> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Nai Nai>\r\n",
        "Hu Jiao <Nai Nai>\r\n",
        "Gei <Wai Gong> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Wai Gong>\r\n",
        "Hu Jiao <Wai Gong>\r\n",
        "Gei <Wai Po> Da Dian Hua\r\n",
        "Da Dian Hua Gei <Wai Po>\r\n",
        "Hu Jiao <Wai Po>\r\n",
    };
    HET_LOGD("ai s32ChnSampleRate %d\r\n", params->s32ChnSampleRate);
    if (params->s32ChnSampleRate == 16000)
        s32AiAlgoFrames = AI_ALGO_FRAMES;
    else if (params->s32ChnSampleRate == 8000)
        s32AiAlgoFrames = (AI_ALGO_FRAMES >> 1);

    /* Do not dump if s32AiAlgoFrames is invalid */
    if (s32AiAlgoFrames == 0)
        params->s32DumpAlgo = 0;
    rmfile[0]='\0';
    HET_LOGD("ai s32DumpAlgo %d s32AiAlgoFrames %d\r\n", params->s32DumpAlgo,s32AiAlgoFrames);
    if (params->s32DumpAlgo) {
        buf_aed = (RK_S16 *)calloc(s32AiAlgoFrames * 2 * sizeof(RK_S16), 1);
        RK_ASSERT(buf_aed != RK_NULL);
        fp_aed = fopen("/tmp/cap_aed_2ch.pcm", "wb");
        RK_ASSERT(fp_aed != RK_NULL);

        buf_bcd = (RK_S16 *)calloc(s32AiAlgoFrames * 1 * sizeof(RK_S16), 1);
        RK_ASSERT(buf_bcd != RK_NULL);
        fp_bcd = fopen("/tmp/cap_bcd_1ch.pcm", "wb");
        RK_ASSERT(fp_bcd != RK_NULL);

        buf_buz = (RK_S16 *)calloc(s32AiAlgoFrames * 1 * sizeof(RK_S16), 1);
        RK_ASSERT(buf_aed != RK_NULL);
        fp_buz = fopen("/tmp/cap_buz_1ch.pcm", "wb");
        RK_ASSERT(fp_buz != RK_NULL);

        buf_gbs = (RK_S16 *)calloc(s32AiAlgoFrames * 1 * sizeof(RK_S16), 1);
        RK_ASSERT(buf_aed != RK_NULL);
        fp_gbs = fopen("/tmp/cap_gbs_1ch.pcm", "wb");
        RK_ASSERT(fp_gbs != RK_NULL);
    }
    AUDIO_SAVE_FILE_INFO_S save;
    save.u32FileSize = 1024*1024;
    result = HET_AI_CreateChn(params);
    if(result !=0 )
    {
        HET_LOGE("HET_AI_CreateChn fail %d !\r\n", result);
        return NULL;
    }
    while (global_run) {
        if(!ai_run || (get_sound_out_stat() && params->s32loopCount != -1) || (params->s32RecognizerEnable && recFile != NULL)){//在播放音频时，不采集音频
        //if(!ai_run || (params->s32RecognizerEnable && recFile != NULL)){//在播放音频时，也采集音频
            if(!isNeedApply){
                isNeedApply = RK_TRUE;
                HET_LOGI("ai new Apply run -> %d out -> %d !\r\n", ai_run, get_sound_out_stat());
                save.bCfg = RK_FALSE;
                RK_MPI_AI_SaveFile(params->s32DevId, params->s32ChnId, &save);
            }
            //printf(".");
            usleep(10000);
            continue;
        }else{
            //printf("*");
            if(isNeedApply){ 
                HET_LOGI("ai apply\r\n");
                isNeedApply = RK_FALSE;
                // 根据参数设置是否保存文件
                if (params->dstFilePath && params->saveDataFile) {
                    HET_LOGI("ai save\r\n");
                    AUDIO_FILE_STATUS_S fileStatus;
                    memset(&save, 0, sizeof(AUDIO_SAVE_FILE_INFO_S));
                    save.u32FileSize = 1024*1024;
                    RK_MPI_AI_QueryFileStatus(params->s32DevId, params->s32ChnId, &fileStatus);
                    if (fileStatus.bSaving) {
                        save.bCfg = RK_FALSE;
                        HET_LOGI("ai disable file save \r\n");
                        RK_MPI_AI_SaveFile(params->s32DevId, params->s32ChnId, &save);
                    }
                    snprintf(save.aFilePath, sizeof(save.aFilePath) -1, "%s", params->dstFilePath);
                    snprintf(save.aFileName, sizeof(save.aFileName) -1, "%s", params->saveDataFile);
                    HET_LOGI("ai apply file save %d %d %s/%s \r\n", params->s32DevId, params->s32ChnId, params->dstFilePath,params->saveDataFile);
                    save.bCfg = RK_TRUE;
                    RK_MPI_AI_SaveFile(params->s32DevId, params->s32ChnId, &save);
                    HET_LOGI("ai apply file save finish\r\n");
                }else{
                    HET_LOGI("ai disable save\r\n");
                    save.bCfg = RK_FALSE;
                    RK_MPI_AI_SaveFile(params->s32DevId, params->s32ChnId, &save);
                }
                if(params->s32RecognizerEnable)
                {
                    //如果有在录音，删除当前当音
                    if(fp_r){
                        fclose(fp_r);
                        fp_r = NULL;
                        memset(rmfile,0,sizeof(rmfile));
                        snprintf(rmfile,sizeof(rmfile) - 1,"rm -f %s",filename);
                        HET_LOGD("rm cmd:%s\r\n", rmfile);
                        system(rmfile);
                    }
                    //清除录音单缓存
                    rb_reset(&audioRecBuf);
                }
            }
        }
        if(params->s32RecognizerEnable)
        {
            //HET_LOGD("ai s32AedEnable %d\r\n", params->s32AedEnable);
            if (params->s32AedEnable == 2) {
                if ((aed_count + 1) % 50 == 0) {
                    result = RK_MPI_AI_DisableAed(params->s32DevId, params->s32ChnId);
                    if (result != RK_SUCCESS) {
                        HET_LOGE("RK_MPI_AI_DisableAed(%d,%d) failed with %#x\r\n",
                                params->s32DevId, params->s32ChnId, result);
                        return RK_NULL;
                    }
                    if (aed_flag) {
                        HET_LOGD(" - aed_count=%ld apply_ai_aed\r\n", aed_count);
                        apply_ai_aed(params);
                        aed_flag = 0;
                    } else {
                        HET_LOGD(" - aed_count=%ld apply_ai_aed2\r\n", aed_count);
                        apply_ai_aed(params);
                        aed_flag = 1;
                    }
                }
                aed_count++;
            }
            
            //HET_LOGD("ai s32BcdEnable %d\r\n", params->s32BcdEnable);
            if (params->s32BcdEnable == 2) {
                if ((bcd_count + 1) % 50 == 0) {
                    result = RK_MPI_AI_DisableBcd(params->s32DevId, params->s32ChnId);
                    if (result != RK_SUCCESS) {
                        HET_LOGE("RK_MPI_AI_DisableBcd(%d,%d) failed with %#x\r\n",
                                params->s32DevId, params->s32ChnId, result);
                        return RK_NULL;
                    }
                    if (bcd_flag) {
                        HET_LOGD(" - bcd_count=%ld apply_ai_bcd\r\n", bcd_count);
                        apply_ai_bcd(params);
                        bcd_flag = 0;
                    } else {
                        HET_LOGD(" - bcd_count=%ld apply_ai_bcd2\r\n", bcd_count);
                        apply_ai_bcd(params);
                        bcd_flag = 1;
                    }
                }
                bcd_count++;
            }
            
            //HET_LOGD("ai s32BuzEnable %d\r\n", params->s32BuzEnable);
            if (params->s32BuzEnable == 2) {
                if ((buz_count + 1) % 50 == 0) {
                    result = RK_MPI_AI_DisableBuz(params->s32DevId, params->s32ChnId);
                    if (result != RK_SUCCESS) {
                        HET_LOGE("RK_MPI_AI_DisableBuz(%d,%d) failed with %#x\r\n",
                                params->s32DevId, params->s32ChnId, result);
                        return RK_NULL;
                    }
                    if (buz_flag) {
                        HET_LOGD(" - buz_count=%ld apply_ai_buz\r\n", buz_count);
                        apply_ai_buz(params);
                        buz_flag = 0;
                    } else {
                        HET_LOGD(" - buz_count=%ld apply_ai_buz2\r\n", buz_count);
                        apply_ai_buz(params);
                        buz_flag = 1;
                    }
                }
                buz_count++;
            }
            //HET_LOGD("ai s32GbsEnable %d\r\n", params->s32GbsEnable);
            if (params->s32GbsEnable == 2) {
                if ((gbs_count + 1) % 50 == 0) {
                    result = RK_MPI_AI_DisableGbs(params->s32DevId, params->s32ChnId);
                    if (result != RK_SUCCESS) {
                        HET_LOGE("RK_MPI_AI_DisableGbs(%d,%d) failed with %#x\r\n",
                                params->s32DevId, params->s32ChnId, result);
                        return RK_NULL;
                    }
                    if (gbs_flag) {
                        HET_LOGD(" - gbs_count=%ld apply_ai_gbs\r\n", gbs_count);
                        apply_ai_gbs(params);
                        gbs_flag = 0;
                    } else {
                        HET_LOGD(" - gbs_count=%ld apply_ai_gbs2\r\n", gbs_count);
                        //params->s32GbsFrameLen = ;
                        apply_ai_gbs(params);
                        gbs_flag = 1;
                    }
                }
                gbs_count++;
            }
            result = RK_MPI_AI_GetFrame(params->s32DevId, params->s32ChnId, &getFrame, RK_NULL, s32MilliSec);
            if (result == 0) {
                void* data = RK_MPI_MB_Handle2VirAddr(getFrame.pMbBlk);
                //HET_LOGV("data = %p, len = %d\r\n", data, getFrame.u32Len);
                if (getFrame.u32Len <= 0) {
                    HET_LOGE("get ai frame end\r\n");
                    break;
                }    
                if(params->s32AedRecing){
                    if(fp_r)
                        fwrite(data, getFrame.u32Len, 1, fp_r);
                }else{
                    if(params->s32loopCount > 0){
                        if(!fp_r){
                            memset(filename,0,sizeof(filename));
                            fileCount++;
                            if(fileCount > 10000)
                                fileCount = 1;
                            snprintf(filename, sizeof(filename)-1, "/userdata/cap_out_r%d.pcm",fileCount);
                            fp_r = fopen(filename, "wb");
                            RK_ASSERT(fp_r != RK_NULL);
                        } 
                        if(fp_r)
                            fwrite(data, getFrame.u32Len, 1, fp_r);
                    }else{
                        if(rb_push(&audioRecBuf,(char *)data, getFrame.u32Len) == -1){
                            HET_LOGI("data = %p, len = %d\r\n", data, getFrame.u32Len);
                            // 超出了，先从fifo丢掉部分数据，再保存新数据
                            rb_pop(&audioRecBuf, NULL, getFrame.u32Len);
                            rb_push(&audioRecBuf,(char *)data, getFrame.u32Len);
                        }
                    }
                }
                RK_MPI_AI_ReleaseFrame(params->s32DevId, params->s32ChnId, &getFrame, RK_NULL);
            }


            // dump results of VQE module
            if (params->s32VqeEnable && params->s32VqeResult) {
                AI_VQE_RESULT_S vqe_result;

                memset(&vqe_result, 0, sizeof(vqe_result));
                result = RK_MPI_AI_GetVqeResult(params->s32DevId, params->s32ChnId, &vqe_result);
                if (result == 0) {
                    if (vqe_result.s32WakeupMode & 0x02) {
                        if (vqe_result.s32WakeupStatus > 0 && vqe_result.s32WakeupStatus <= 1)
                            HET_LOGD("VQE Result: mode2 wakeup word[%d]:\"%s\"\r\n",
                                    vqe_result.s32WakeupStatus, mode2_wakeup_words[vqe_result.s32WakeupStatus]);
                        if (vqe_result.s32WakeupCmdID > 0 && vqe_result.s32WakeupCmdID <= 18) {
                            HET_LOGD("VQE Result: mode2 command word[%d]:\"%s\" score:%f\r\n",
                                    vqe_result.s32WakeupCmdID,
                                    mode2_command_words[vqe_result.s32WakeupCmdID],
                                    vqe_result.s32WakeupCmdScore);
                        }
                    } else if (vqe_result.s32WakeupMode & 0x01) {
                        if (vqe_result.s32WakeupStatus > 0 && vqe_result.s32WakeupStatus <= 7)
                            HET_LOGD("VQE Result: mode1 wakeup word[%d]:\"%s\"\r\n",
                                    vqe_result.s32WakeupStatus, mode1_wakeup_words[vqe_result.s32WakeupStatus]);
                    }
                }
            }

            // dump results of SED(AED/BCD) modules
            if (params->s32AedEnable) {
                AI_AED_RESULT_S aed_result;

                memset(&aed_result, 0, sizeof(aed_result));
                result = RK_MPI_AI_GetAedResult(params->s32DevId, params->s32ChnId, &aed_result);
                if (result == 0) {
                    if (aed_result.bAcousticEventDetected){
                        // 语音信噪比事件检测结果，1为满足信噪比阈值，0不满足。
                        //HET_LOGD("AED Result: AcousticEvent:%d\r\n",aed_result.bAcousticEventDetected);
                        params->s32AedAcousticLowCount = 0;
                        params->s32AedAcousticHighCount++;
                        if(!params->s32AedRecing){
                            if(params->s32AedAcousticHighCount > params->s32AedAcousticRecCountMax){
                                params->s32AedRecing = 1;
                                HET_LOGD("AED Result: start rec:\r\n");
                                if(!fp_r){
                                    // 检查到声音，进行录音
                                    memset(filename,0,sizeof(filename));
                                    snprintf(filename, sizeof(filename)-1, "/userdata/cap_out_r%d.pcm",fileCount++);
                                    fp_r = fopen(filename, "wb");
                                    RK_ASSERT(fp_r != RK_NULL);
                                    int popLen=0;
                                    //如果有缓存数据，加入录单中
                                    do{
                                        popLen =  rb_pop(&audioRecBuf,cacheBuf,1024);
                                        if(popLen && fp_r)
                                            fwrite(cacheBuf, popLen, 1, fp_r);
                                    } while(popLen > 0);
                                }
                            }
                        }
                    }else{
                        params->s32AedAcousticLowCount++;
                        if(params->s32AedRecing){
                            if(params->s32AedAcousticLowCount > params->s32AedAcousticMuteCountMax){
                                // 一次识别结束，保存录音
                                HET_LOGD("AED Result: end rec:%d\r\n",params->s32AedAcousticHighCount);
                                if(fp_r){
                                    fflush(fp_r);
                                    fclose(fp_r);
                                    fp_r = NULL;
                                }
                                //HET_LOGD("speechRecognizerPut:count %d/%d\r\n", params->s32AedAcousticHighCount, params->s32AedSaveRecCountMin);
                                if(params->s32AedAcousticHighCount>params->s32AedSaveRecCountMin){
                                    if(params->s32loopCount > 0) {
                                        HET_LOGI("rec:ready:%s loop %d\r\n", filename,params->s32loopCount);
                                        params->s32loopCount--;
                                        if(params->s32loopCount == 0){
                                            recFile = filename;
                                            ai_run = 0;
                                            HET_LOGI("rec:finish data %s\r\n", filename);
                                            //speechRecognizerPut(filename);
                                        }
                                    }else if(params->s32loopCount == -1) {
                                        HET_LOGI("rec:new data %s loop %d\r\n", filename,params->s32loopCount);
                                        // 如果在播放，要打断
                                        if(get_sound_out_stat()){
			                                rb_reset(&audioPlayBuf);
                                        }
                                        speechRecognizerPut(filename,true);
                                    }else{
                                        ai_run = 0;
                                        het_ai_clean_rec_file(filename);
                                    }
                                }
                                if(!recFile){
                                    memset(rmfile,0,sizeof(rmfile));
                                    snprintf(rmfile,sizeof(rmfile) - 1,"rm -f %s",filename);
                                    HET_LOGD("rm cmd:%s\r\n", rmfile);
                                    system(rmfile);
                                }
                                params->s32AedAcousticHighCount = 0;
                                params->s32AedRecing = 0;
                            }
                        }else{
                            if(params->s32AedAcousticLowCount > params->s32AedAcousticEndCountMax){
                                //HET_LOGD("AED Result: finish rec:%d\r\n",params->s32AedAcousticHighCount);
                                params->s32AedAcousticLowCount = 0;
                            }
                        }
                    }
                    if (aed_result.bLoudSoundDetected) {
                        // 超大声事件检测结果，1为满足超大声阈值，0不满足。
                        params->s32AedLoudCount++;
                        //HET_LOGD("AED Result: LoudSound:%d\r\n",aed_result.bLoudSoundDetected);
                    }

                    if (aed_result.bLoudSoundDetected){
                        // 超大声检测得到的音量大小，以 db 为单位。
                        //HET_LOGD("AED Result: LoudSound Volume Result:%f db\r\n",aed_result.lsdResult);
                    }
                }
                if (params->s32DumpAlgo) {
                    for (RK_S32 i = 0; i < s32AiAlgoFrames; i++) {
                        *(buf_aed + 2 * i + 0) = 10000 * aed_result.bAcousticEventDetected;
                        *(buf_aed + 2 * i + 1) = 10000 * aed_result.bLoudSoundDetected;
                    }
                    fwrite(buf_aed, s32AiAlgoFrames * 2 * sizeof(RK_S16), 1, fp_aed);
                }
            }

#if 0
            if (params->s32BcdEnable) {
                AI_BCD_RESULT_S bcd_result;

                memset(&bcd_result, 0, sizeof(bcd_result));
                result = RK_MPI_AI_GetBcdResult(params->s32DevId, params->s32ChnId, &bcd_result);
                if (result == 0 && bcd_result.bBabyCry) {
                    params->s32BcdCount++;
                    HET_LOGD("BCD Result: BabyCry:%d\r\n", bcd_result.bBabyCry);
                }
                if (params->s32DumpAlgo) {
                    for (RK_S32 i = 0; i < s32AiAlgoFrames; i++) {
                        *(buf_bcd + 1 * i) = 10000 * bcd_result.bBabyCry;
                    }
                    fwrite(buf_bcd, s32AiAlgoFrames * 1 * sizeof(RK_S16), 1, fp_bcd);
                }
            }

            if (params->s32BuzEnable) {
                AI_BUZ_RESULT_S buz_result;

                memset(&buz_result, 0, sizeof(buz_result));
                result = RK_MPI_AI_GetBuzResult(params->s32DevId, params->s32ChnId, &buz_result);
                if (result == 0 && buz_result.bBuzz) {
                    params->s32BuzCount++;
                    HET_LOGD("BUZ Result: Buzz:%d\r\n", buz_result.bBuzz);
                }
                if (params->s32DumpAlgo) {
                    for (RK_S32 i = 0; i < s32AiAlgoFrames; i++) {
                        *(buf_buz + 1 * i) = 10000 * buz_result.bBuzz;
                    }
                    fwrite(buf_buz, s32AiAlgoFrames * 1 * sizeof(RK_S16), 1, fp_buz);
                }
            }

            if (params->s32GbsEnable) {
                AI_GBS_RESULT_S gbs_result;

                memset(&gbs_result, 0, sizeof(gbs_result));
                result = RK_MPI_AI_GetGbsResult(params->s32DevId, params->s32ChnId, &gbs_result);
                if (result == 0 && gbs_result.bGbs) {
                    params->s32GbsCount++;
                    HET_LOGD("GBS Result: Gbs:%d\r\n", gbs_result.bGbs);
                }
                if (params->s32DumpAlgo) {
                    for (RK_S32 i = 0; i < s32AiAlgoFrames; i++) {
                        *(buf_gbs + 1 * i) = 10000 * gbs_result.bGbs;
                    }
                    fwrite(buf_gbs, s32AiAlgoFrames * 1 * sizeof(RK_S16), 1, fp_gbs);
                }
            }
#endif
        }else{
             result = RK_MPI_AI_GetFrame(params->s32DevId, params->s32ChnId, &getFrame, RK_NULL, s32MilliSec);
            if (result == 0) {
                RK_MPI_AI_ReleaseFrame(params->s32DevId, params->s32ChnId, &getFrame, RK_NULL);
            }
            //HET_LOGD("~\r\n");         
            usleep(10000);  
        }
    }

	HET_LOGD("%s  clean %d \r\n", __func__,global_run);
    if (params->s32DumpAlgo) {
        if (buf_aed)
            free(buf_aed);
        if (buf_bcd)
            free(buf_bcd);
        if (buf_buz)
            free(buf_buz);
        if (buf_gbs)
            free(buf_gbs);

        if (fp_aed)
            fclose(fp_aed);
        if (fp_bcd)
            fclose(fp_bcd);
        if (fp_buz)
            fclose(fp_buz);
        if (fp_gbs)
            fclose(fp_gbs);
    }
	
    if (fp_r)
        fclose(fp_r);
    
    HET_AI_DestroyChn(params);
	HET_LOGD("%s quit!\r\n", __func__);
    return RK_NULL;
}
/******************************************************************************
 * function : ai thread
 ******************************************************************************/
/**
 * @brief 音频处理线程
 * @param pArgs 音频参数
 * @return 成功返回0，失败返回-1
 */
void *HET_AI_Get_Stream_Thread(void *pArgs) {
	HET_AI_CTX_S *ctx = (HET_AI_CTX_S *)(pArgs);
	
	HET_LOGD("HET_AI_Get_Stream_Thread enter\r\n");
	RK_S32 s32Ret = RK_FAILURE;
	bool bCheckLow = false;
	RK_U8 *pAudioData = RK_NULL;
	ctx->s32PeriodCount = ctx->s32ChnCnt * (8<<ctx->s32BitWidth) / 8;
	ctx->AudioSize = ctx->s32ChnSampleRate * ctx->s32PeriodCount * 5;//16000*4*5
	HET_LOGD("#Device: %s\r\n", ctx->cardName?ctx->cardName:"NULL");
	HET_LOGD("#SampleRate: %d\r\n", ctx->s32ChnSampleRate);
	HET_LOGD("#Channel Count: %d\r\n", ctx->s32ChnCnt);
	HET_LOGD("#Loop Count: %d\r\n", ctx->s32loopCount);
	HET_LOGD("#Output Path: %s\r\n", ctx->dstFilePath?ctx->dstFilePath:"NULL");
	HET_LOGD("#saveFile Path: %s\r\n", ctx->saveDataFile?ctx->saveDataFile:"NULL");
	HET_LOGD("#PeriodCount: %d\r\n", ctx->s32PeriodCount);
	HET_LOGD("#AudioSize: %d\r\n", ctx->AudioSize);
	// Init AI[0]
	ctx->s32DevId = AI_DEV_ID;
	ctx->s32ChnId = AI_CHN_ID;
	ctx->stAiAttr.soundCard.channels = ctx->s32DeviceChannel;
	ctx->stAiAttr.soundCard.sampleRate = ctx->s32DeviceSampleRate;
	ctx->stAiAttr.soundCard.bitWidth = (AUDIO_BIT_WIDTH_E)ctx->s32BitWidth;
	ctx->stAiAttr.enBitwidth = (AUDIO_BIT_WIDTH_E)ctx->s32BitWidth;
	ctx->stAiAttr.enSamplerate = (AUDIO_SAMPLE_RATE_E)ctx->s32ChnSampleRate;
	ctx->stAiAttr.enSoundmode = HET_AI_Find_Sound_Mode(ctx->s32ChnCnt);
	ctx->stAiAttr.u32FrmNum = ctx->s32PeriodCount;
	ctx->stAiAttr.u32PtNumPerFrm = ctx->s32PeriodSize;
	if(!ctx->s32DataReadEnable)
		ctx->stAiAttr.u32EXFlag = 0;
	else
		ctx->stAiAttr.u32EXFlag = 0;

	ctx->stAiAttr.u32ChnCnt = ctx->s32ChnCnt;
	if (ctx->cardName) {
		strcpy((char *)ctx->stAiAttr.u8CardName, ctx->cardName);
	}
	mpi_ai_attr_show_options(&ctx->stAiAttr, ctx->s32DevId);
	HET_LOGD("getDataThread!\r\n");
    getDataThread(ctx);
	HET_LOGD("getDataThread exit!\r\n");
    HET_LOGD(" HET_AI_DestroyChn!\r\n");
    HET_AI_DestroyChn(ctx);
	HET_LOGD("%s quit!\r\n", __func__);
    return RK_NULL;
}
